package com.demo.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

//用XML方式定义切面、切入点，这里只包含通知(完整版本)
public class XmlAspect2 {
    //前置通知
    public void before(JoinPoint joinPoint){
        System.out.print("这是前置通知(执行准备或预检任务)");
        System.out.print("目标对象是："+joinPoint.getTarget());
        System.out.println("，被织入的目标方法为："+
                joinPoint.getSignature().getName());
    }

    //返回通知
    //返回通知和后置通知的区别：
    //1.返回通知可以获取目标函数的返回值，但是后置通知不能获取
    //2.返回通知只能在目标方法正常调用时被调用，目标方法如果抛异常是不被调用的。后通知无论目标方法是否正常执行，都会被调用。
    //参考 https://blog.csdn.net/SR9949/article/details/80357065
    public void afterReturning(JoinPoint joinPoint,Object result){
        System.out.print("这是返回通知（方法不出现异常时调用）!");
        System.out.println("被织入的目标方法为："+
                joinPoint.getSignature().getName());
        System.out.println("返回结果是："+result);
    }
    /**
     * 环绕通知
     * ProceedingJoinPoint 是JoinPoint子接口，用于控制目标方法的执行
     * 1.必须是Object类型的返回值
     * 2.必须接收一个参数，类型为ProceedingJoinPoint
     * 3.必须throws Throwable
     */
    public Object around(ProceedingJoinPoint point)throws Throwable{
        System.out.println("这是环绕通知，在目标方法执行之前的部分(执行权限检查这样的前置任务)");
        //调用目标方法
        Object object=point.proceed();
        System.out.println("这是环绕通知，在目标方法执行之后的部分(执行日志记录这样的后置任务)");
        return object;
    }
    //异常通知(有Exception参数的情况)
    //仅用于处理已抛出的异常，无法阻止异常传播，参考 https://developer.aliyun.com/article/1677688
    //要终止异常传播，选用around通知
    public void afterException(Exception ex){
        System.out.println("异常通知！");
        System.out.println(ex.getMessage());
    }
    //异常通知(无Exception参数的情况)
//    public void afterException(){
//        System.out.println("异常通知！");
//    }

    //后置通知
    public void after(JoinPoint joinPoint){
        System.out.print("这是后置(最终)通知(执行清理或收尾任务)");
        System.out.println("被织入的目标方法为："+
                joinPoint.getSignature().getName());
    }
}